package craky.keeper;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.JTextComponent;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;

import craky.component.JImagePane;
import craky.componentc.GridBorder;
import craky.componentc.JCButton;
import craky.componentc.JCCheckBox;
import craky.componentc.JCComboBox;
import craky.componentc.JCLabel;
import craky.componentc.JCLimitedPassword;
import craky.keeper.user.User;
import craky.keeper.user.UserDAO;
import craky.keeper.user.UserInfoDialog;
import craky.keeper.util.KeeperUtil;
import craky.layout.LineLayout;
import craky.util.Config;
import craky.util.UIUtil;

public class LoginFrame extends JFrame {
	private static final long serialVersionUID = -3144576417706510085L;
	private KeeperApp keeper;
	private Config loginConfig;
	private JComponent content;
	private JImagePane bannerPane;
	private JCButton btnOk;
	private JCButton btnCancel;
	private JCComboBox comboUser;
	private JCLimitedPassword txtPsd;
	private JCCheckBox cbSavePsd;
	private JCCheckBox cbAuto;
	private JCLabel lbDelUserInfo;
	private JCLabel lbModifyPsd;
	private boolean godReleased;

	public LoginFrame(KeeperApp keeper) {
		this.keeper = keeper;
		this.loginConfig = keeper.getLoginConfig();
		initUI();
		initBanner();
		initHistory();
		setVisible(true);
	}

	private void initUI() {
		this.content = ((JComponent) getContentPane());
		setTitle("三号管家");
		setIconImage(KeeperUtil.getImage("logo_16.png"));
		this.content.setPreferredSize(new Dimension(334, 218));
		this.content.setLayout(new BorderLayout());
		this.content.setBorder(new EmptyBorder(0, 0, 0, 0));
		this.content.setBackground(Color.WHITE);
		setDefaultCloseOperation(3);
		setResizable(false);
		initContent();
		getRootPane().setDefaultButton(this.btnOk);
		pack();
		setLocationRelativeTo(null);
	}

	private void initContent() {
		ActionHandler actionListener = new ActionHandler();
		this.bannerPane = new JImagePane();
		JPanel centerPane = new JPanel();
		JImagePane bottomPane = new JImagePane();
		this.btnOk = new JCButton("确定");
		this.btnCancel = new JCButton("取消");
		this.bannerPane.setPreferredSize(new Dimension(334, 64));
		this.bannerPane.setMode("Tiled");
		bottomPane.setPreferredSize(new Dimension(334, 30));
		bottomPane.setImage(KeeperUtil.getImage("login_bottom.png"));
		bottomPane.setBorder(new EmptyBorder(0, 0, 0, 0));
		bottomPane.setLayout(new LineLayout(5, 0, 7, 5, 0, 10, 10, 0));
		centerPane.setBackground(new Color(228, 244, 255));
		centerPane.setBorder(new GridBorder(Color.WHITE, 0, 1, 0, 1));
		centerPane.setLayout(new LineLayout(0, 0, 0, 0, 0, 10, 10, 1));
		this.btnOk.setPreferredSize(new Dimension(69, 21));
		this.btnCancel.setPreferredSize(this.btnOk.getPreferredSize());
		initCenterPane(centerPane);
		bottomPane.add(this.btnOk, "End");
		bottomPane.add(this.btnCancel, "End");
		this.content.add(this.bannerPane, "North");
		this.content.add(bottomPane, "South");
		this.content.add(centerPane, "Center");
		this.btnOk.addActionListener(actionListener);
		this.btnCancel.addActionListener(actionListener);
	}

	private void initCenterPane(JPanel centerPane) {
		MouseHandler mouseListener = new MouseHandler();
		ItemHandler itemListener = new ItemHandler();
		EditHandler editListener = new EditHandler();
		JCLabel lbUser = new JCLabel("用户名：");
		JCLabel lbPsd = new JCLabel("密     码：");
		this.lbDelUserInfo = new JCLabel("删除记录");
		this.lbModifyPsd = new JCLabel("修改密码");
		this.comboUser = new JCComboBox();
		this.txtPsd = new JCLimitedPassword(100);
		this.cbSavePsd = new JCCheckBox("记住密码");
		this.cbAuto = new JCCheckBox("自动登陆");
		EmptyComponent ecUser = new EmptyComponent();
		EmptyComponent ecPsd = new EmptyComponent();
		EmptyComponent ecStatus = new EmptyComponent();

		ecUser.setLayout(new LineLayout(0, 0, 0, 14, 0, 0, 10, 0));
		ecUser.setPreferredSize(new Dimension(-1, 50));
		this.lbDelUserInfo.setBorder(new EmptyBorder(1, 3, 0, 0));
		this.lbDelUserInfo.setPreferredSize(new Dimension(75, 24));
		this.lbDelUserInfo.setForeground(new Color(22, 112, 235));
		this.lbDelUserInfo.setCursor(new Cursor(12));
		lbUser.setBorder(new EmptyBorder(1, 0, 0, 0));
		lbUser.setPreferredSize(new Dimension(74, 24));
		lbUser.setHorizontalAlignment(4);
		this.comboUser.setPreferredSize(new Dimension(-1, 26));
		this.comboUser.setEditable(true);
		this.lbModifyPsd.setBorder(new EmptyBorder(1, 3, 0, 0));
		this.lbModifyPsd
				.setPreferredSize(this.lbDelUserInfo.getPreferredSize());
		this.lbModifyPsd.setForeground(this.lbDelUserInfo.getForeground());
		this.lbModifyPsd.setCursor(new Cursor(12));
		ecPsd.setLayout(new LineLayout(0, 0, 0, 0, 0, 0, 10, 0));
		ecPsd.setPreferredSize(new Dimension(-1, 30));
		this.txtPsd.setPreferredSize(this.comboUser.getPreferredSize());
		lbPsd.setBorder(new EmptyBorder(1, 0, 0, 0));
		lbPsd.setPreferredSize(new Dimension(74, 24));
		lbPsd.setHorizontalAlignment(4);
		ecStatus.setLayout(new LineLayout(12, 105, 0, 0, 0, 10, 10, 0));
		ecStatus.setPreferredSize(new Dimension(-1, 27));

		ecUser.add(lbUser, "Start");
		ecUser.add(this.comboUser, "Middle");
		ecUser.add(this.lbDelUserInfo, "End");
		ecPsd.add(lbPsd, "Start");
		ecPsd.add(this.txtPsd, "Middle");
		ecPsd.add(this.lbModifyPsd, "End");
		ecStatus.add(this.cbSavePsd, "Start");
		ecStatus.add(this.cbAuto, "Start");
		centerPane.add(ecUser, "StartFill");
		centerPane.add(ecPsd, "StartFill");
		centerPane.add(ecStatus, "EedFill");
		this.bannerPane.addMouseListener(mouseListener);
		this.cbSavePsd.addItemListener(itemListener);
		this.cbAuto.addItemListener(itemListener);
		((JTextComponent) this.comboUser.getEditor().getEditorComponent())
				.getDocument().addDocumentListener(editListener);

		UIUtil.actionLabel(this.lbDelUserInfo, new AbstractAction() {
			private static final long serialVersionUID = 1314650981076868723L;

			public void actionPerformed(ActionEvent e) {
				LoginFrame.this.deleteUserInfo();
			}
		});
		UIUtil.actionLabel(this.lbModifyPsd, new AbstractAction() {
			private static final long serialVersionUID = -8098585019722294097L;

			public void actionPerformed(ActionEvent e) {
				LoginFrame.this.modifyPassword();
			}
		});
	}

	private void initBanner() {
		String bannerName = this.keeper.getBannerName();

		if (bannerName != null) {
			Image image = new ImageIcon(KeeperConst.BANNER_DIR
					+ KeeperConst.FILE_SEP + bannerName).getImage();
			this.bannerPane.setImage(image);
		}
	}

	private void initHistory() {
		List<String> history = this.keeper.getLoginHistory();

		if (!history.isEmpty()) {
			for (String name : this.keeper.getLoginHistory()) {
				this.comboUser.addItem(name);
			}
			this.comboUser.setSelectedIndex(0);
			requestPassword(false);
		} else {
			requestUser();
		}
	}

	public void requestUser() {
		this.comboUser.requestFocus();
	}

	public void requestPassword(boolean clear) {
		if (clear) {
			clearPassword();
		}

		this.txtPsd.requestFocus();
	}

	public void clearPassword() {
		this.txtPsd.setText("");
	}

	public boolean isSavePassword() {
		return this.cbSavePsd.isSelected();
	}

	private void setSavePassword(boolean save) {
		this.cbSavePsd.setSelected(save);
	}

	public boolean isAutoLogin() {
		return this.cbAuto.isSelected();
	}

	private void setAutoLogin(boolean auto) {
		this.cbAuto.setSelected(auto);
	}

	private String getSelectedUserName() {
		return ((JTextComponent) this.comboUser.getEditor()
				.getEditorComponent()).getText();
	}

	private void deleteUserInfo() {
		String name = getSelectedUserName();
		this.keeper.removeHistoryUser(name);
		this.comboUser.removeItem(name);

		if (this.comboUser.getItemCount() > 0) {
			this.comboUser.setSelectedIndex(0);
		} else {
			((JTextComponent) this.comboUser.getEditor().getEditorComponent())
					.setText(null);
		}
	}

	private void modifyPassword() {
		String name = getSelectedUserName();
		String failInfo = null;

		if (!User.isAllowedName(name)) {
			failInfo = "非法用户名！";
		} else if (UserDAO.getUsers(
				new Criterion[] { Restrictions.eq("name", name) }).isEmpty()) {
			failInfo = "该用户不存在";
		}

		if (failInfo != null) {
			this.keeper.showMessageBeforeLogin("修改密码", failInfo, true);
			requestUser();
		} else {
			new UserInfoDialog(this.keeper, this, name, true);
		}
	}

	public boolean isGodReleased() {
		return this.godReleased;
	}

	private class ActionHandler implements ActionListener {
		private ActionHandler() {
		}

		public void actionPerformed(ActionEvent e) {
			Object source = e.getSource();

			if (source == LoginFrame.this.btnOk) {
				LoginFrame.this.keeper.login(LoginFrame.this
						.getSelectedUserName(), new String(
						LoginFrame.this.txtPsd.getPassword()));
			} else if (source == LoginFrame.this.btnCancel) {
				System.exit(0);
			}
		}
	}

	private class EditHandler implements DocumentListener {
		private EditHandler() {
		}

		public void insertUpdate(DocumentEvent e) {
			checkState(e);
		}

		public void removeUpdate(DocumentEvent e) {
			checkState(e);
		}

		public void changedUpdate(DocumentEvent e) {
			checkState(e);
		}

		private void checkState(DocumentEvent e) {
			String name = LoginFrame.this.getSelectedUserName();
			boolean savePassword = LoginFrame.this.loginConfig.getProperty(name
					+ ".password") != null;

			if (LoginFrame.this.keeper.getLoginHistory().contains(name)) {
				LoginFrame.this.setAutoLogin(Boolean
						.parseBoolean(LoginFrame.this.loginConfig.getProperty(
								name + ".auto", "false")));
				LoginFrame.this.setSavePassword(savePassword);
			} else {
				LoginFrame.this.setSavePassword(false);
				LoginFrame.this.setAutoLogin(false);
			}

			if (!LoginFrame.this.isSavePassword()) {
				LoginFrame.this.clearPassword();
			}
		}
	}

	private class ItemHandler implements ItemListener {
		private ItemHandler() {
		}

		public void itemStateChanged(ItemEvent e) {
			Object source = e.getSource();
			int state = e.getStateChange();
			String savedPassword = null;

			if (source == LoginFrame.this.cbSavePsd) {
				String name = LoginFrame.this.getSelectedUserName();

				if (state == 2) {
					if (LoginFrame.this.cbAuto.isSelected()) {
						LoginFrame.this.cbAuto.setSelected(false);
					}
				} else if ((savedPassword = LoginFrame.this.loginConfig
						.getProperty(name + ".password")) != null) {
					LoginFrame.this.txtPsd.setText(LoginFrame.this.keeper
							.getPasswordTextWhenSaved(savedPassword));
				}
			} else if ((source == LoginFrame.this.cbAuto) && (state == 1)
					&& (!LoginFrame.this.cbSavePsd.isSelected())) {
				LoginFrame.this.cbSavePsd.setSelected(true);
			}
		}
	}

	private class MouseHandler extends MouseAdapter {
		private MouseHandler() {
		}

		@Override
		public void mouseReleased(MouseEvent e) {
			LoginFrame.this.godReleased = ((e.getSource() == LoginFrame.this.bannerPane)
					&& (e.isAltDown()) && (e.getClickCount() == 3) && (SwingUtilities
					.isRightMouseButton(e)));
		}
	}
}